package com.example.smartwaterapi.controller;

import com.example.smartwaterapi.common.api.RestApiResponse;
import com.example.smartwaterapi.service.DegradationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 限流监控管理接口
 * 用于实时查看限流状态和动态调整限流配置
 */
@Slf4j
@Tag(name = "限流监控管理API", description = "限流状态监控和配置管理接口")
@RestController
@RequestMapping("/api/admin/rate-limit")
@PreAuthorize("hasRole('ADMIN')") // 只有管理员可以访问
public class RateLimitMonitorController {
    
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private DegradationService degradationService;
    
    /**
     * 获取限流统计信息
     */
    @Operation(summary = "获取限流统计", description = "获取系统整体限流统计信息")
    @GetMapping("/stats")
    public RestApiResponse<Map<String, Object>> getRateLimitStats() {
        log.info("获取限流统计信息");
        
        Map<String, Object> stats = new HashMap<>();
        
        try {
            // 获取IP限流统计
            Map<String, Object> ipStats = getIpRateLimitStats();
            stats.put("ipStats", ipStats);
            
            // 获取用户限流统计
            Map<String, Object> userStats = getUserRateLimitStats();
            stats.put("userStats", userStats);
            
            // 获取降级统计
            Map<String, Object> degradationStats = getDegradationStats();
            stats.put("degradationStats", degradationStats);
            
            // 系统状态
            stats.put("systemStatus", getSystemStatus());
            stats.put("timestamp", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            
            return RestApiResponse.ok(stats);
            
        } catch (Exception e) {
            log.error("获取限流统计信息失败", e);
            return RestApiResponse.error("获取统计信息失败: " + e.getMessage());
        }
    }
    
    /**
     * 获取特定用户的限流状态
     */
    @Operation(summary = "获取用户限流状态", description = "查看指定用户的限流状态")
    @GetMapping("/user/{userId}")
    public RestApiResponse<Map<String, Object>> getUserRateLimitStatus(
            @Parameter(description = "用户ID") @PathVariable Long userId) {
        
        log.info("获取用户限流状态, userId: {}", userId);
        
        Map<String, Object> userStatus = new HashMap<>();
        
        try {
            // 注意：不包含auth，因为认证接口不使用用户限流
            String[] apiTypes = {"water", "user", "device", "stats", "upload", "default"};
            
            for (String apiType : apiTypes) {
                String redisKey = String.format("user_rate_limit:%d:%s", userId, apiType);
                
                // 获取当前窗口内的访问次数
                Long count = redisTemplate.opsForZSet().zCard(redisKey);
                int currentCount = (count != null) ? count.intValue() : 0;
                
                // 获取最近访问时间
                Set<Object> recentAccess = redisTemplate.opsForZSet().reverseRange(redisKey, 0, 0);
                String lastAccessTime = "";
                if (recentAccess != null && !recentAccess.isEmpty()) {
                    String lastAccess = recentAccess.iterator().next().toString();
                    if (lastAccess.contains(":")) {
                        try {
                            long timestamp = Long.parseLong(lastAccess.split(":")[0]);
                            lastAccessTime = new Date(timestamp).toString();
                        } catch (Exception e) {
                            lastAccessTime = "解析失败";
                        }
                    }
                }
                
                Map<String, Object> apiStatus = new HashMap<>();
                apiStatus.put("currentCount", currentCount);
                apiStatus.put("lastAccessTime", lastAccessTime);
                apiStatus.put("isLimited", currentCount >= getApiLimit(apiType));
                
                userStatus.put(apiType, apiStatus);
            }
            
            userStatus.put("userId", userId);
            userStatus.put("checkTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            
            return RestApiResponse.ok(userStatus);
            
        } catch (Exception e) {
            log.error("获取用户限流状态失败, userId: {}", userId, e);
            return RestApiResponse.error("获取用户状态失败: " + e.getMessage());
        }
    }
    
    /**
     * 临时调整用户限流配置
     */
    @Operation(summary = "临时调整用户限流", description = "临时调整指定用户的限流配置")
    @PostMapping("/user/{userId}/adjust")
    public RestApiResponse<Boolean> adjustUserRateLimit(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @RequestBody UserRateLimitAdjustRequest request) {
        
        log.info("临时调整用户限流配置, userId: {}, request: {}", userId, request);
        
        try {
            String configKey = String.format("dynamic_rate_limit:user:%d:%s", userId, request.getApiType());
            
            Map<String, Object> config = new HashMap<>();
            config.put("maxRequests", request.getMaxRequests());
            config.put("windowSeconds", request.getWindowSeconds());
            config.put("reason", request.getReason());
            config.put("adjustTime", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
            config.put("adjustBy", "admin"); // 可以从安全上下文获取管理员信息
            
            // 设置临时配置，默认1小时过期
            redisTemplate.opsForValue().set(configKey, config, 1, TimeUnit.HOURS);
            
            log.info("用户限流配置调整成功, userId: {}, apiType: {}", userId, request.getApiType());
            
            return RestApiResponse.ok(true);
            
        } catch (Exception e) {
            log.error("调整用户限流配置失败, userId: {}", userId, e);
            return RestApiResponse.error("调整配置失败: " + e.getMessage());
        }
    }
    
    /**
     * 启用系统降级模式
     */
    @Operation(summary = "启用系统降级", description = "启用指定API类型的系统降级模式")
    @PostMapping("/degradation/enable")
    public RestApiResponse<Boolean> enableDegradation(@RequestBody DegradationRequest request) {
        log.info("启用系统降级模式: {}", request);
        
        try {
            degradationService.enableSystemDegradation(request.getApiType(), request.getDurationMinutes());
            return RestApiResponse.ok(true);
        } catch (Exception e) {
            log.error("启用系统降级模式失败", e);
            return RestApiResponse.error("启用降级模式失败: " + e.getMessage());
        }
    }
    
    /**
     * 关闭系统降级模式
     */
    @Operation(summary = "关闭系统降级", description = "关闭指定API类型的系统降级模式")
    @PostMapping("/degradation/disable")
    public RestApiResponse<Boolean> disableDegradation(@RequestParam String apiType) {
        log.info("关闭系统降级模式: {}", apiType);
        
        try {
            degradationService.disableSystemDegradation(apiType);
            return RestApiResponse.ok(true);
        } catch (Exception e) {
            log.error("关闭系统降级模式失败", e);
            return RestApiResponse.error("关闭降级模式失败: " + e.getMessage());
        }
    }
    
    /**
     * 清除用户限流记录
     */
    @Operation(summary = "清除用户限流记录", description = "清除指定用户的限流记录")
    @DeleteMapping("/user/{userId}/clear")
    public RestApiResponse<Boolean> clearUserRateLimit(
            @Parameter(description = "用户ID") @PathVariable Long userId,
            @RequestParam(required = false) String apiType) {
        
        log.info("清除用户限流记录, userId: {}, apiType: {}", userId, apiType);
        
        try {
            if (apiType != null) {
                // 清除特定API类型的限流记录
                String redisKey = String.format("user_rate_limit:%d:%s", userId, apiType);
                redisTemplate.delete(redisKey);
            } else {
                // 清除用户所有限流记录
                String pattern = String.format("user_rate_limit:%d:*", userId);
                Set<String> keys = redisTemplate.keys(pattern);
                if (keys != null && !keys.isEmpty()) {
                    redisTemplate.delete(keys);
                }
            }
            
            log.info("用户限流记录清除成功, userId: {}", userId);
            return RestApiResponse.ok(true);
            
        } catch (Exception e) {
            log.error("清除用户限流记录失败, userId: {}", userId, e);
            return RestApiResponse.error("清除记录失败: " + e.getMessage());
        }
    }
    
    // 辅助方法
    
    private Map<String, Object> getIpRateLimitStats() {
        Map<String, Object> ipStats = new HashMap<>();
        
        try {
            // 统计IP限流记录
            Set<String> ipKeys = redisTemplate.keys("rate_limit:ip:*");
            int totalIpRecords = (ipKeys != null) ? ipKeys.size() : 0;
            
            ipStats.put("totalIpRecords", totalIpRecords);
            ipStats.put("activeIps", totalIpRecords); // 简化统计
            
        } catch (Exception e) {
            log.error("获取IP限流统计失败", e);
            ipStats.put("error", e.getMessage());
        }
        
        return ipStats;
    }
    
    private Map<String, Object> getUserRateLimitStats() {
        Map<String, Object> userStats = new HashMap<>();
        
        try {
            // 统计用户限流记录
            Set<String> userKeys = redisTemplate.keys("user_rate_limit:*");
            
            Set<String> activeUsers = new HashSet<>();
            if (userKeys != null) {
                for (String key : userKeys) {
                    String[] parts = key.split(":");
                    if (parts.length >= 3) {
                        activeUsers.add(parts[2]); // 用户ID
                    }
                }
            }
            
            userStats.put("totalUserRecords", userKeys != null ? userKeys.size() : 0);
            userStats.put("activeUsers", activeUsers.size());
            
        } catch (Exception e) {
            log.error("获取用户限流统计失败", e);
            userStats.put("error", e.getMessage());
        }
        
        return userStats;
    }
    
    private Map<String, Object> getDegradationStats() {
        Map<String, Object> degradationStats = new HashMap<>();
        
        try {
            // 统计降级记录
            Set<String> degradationKeys = redisTemplate.keys("system_degradation:*");
            degradationStats.put("activeDegradations", degradationKeys != null ? degradationKeys.size() : 0);
            
            // 统计降级指标
            String metricsPattern = "degradation_metrics:*";
            Set<String> metricsKeys = redisTemplate.keys(metricsPattern);
            degradationStats.put("metricsRecords", metricsKeys != null ? metricsKeys.size() : 0);
            
        } catch (Exception e) {
            log.error("获取降级统计失败", e);
            degradationStats.put("error", e.getMessage());
        }
        
        return degradationStats;
    }
    
    private Map<String, Object> getSystemStatus() {
        Map<String, Object> systemStatus = new HashMap<>();
        systemStatus.put("healthy", true);
        systemStatus.put("rateLimitEnabled", true);
        systemStatus.put("degradationEnabled", true);
        systemStatus.put("lastCheck", LocalDateTime.now().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        return systemStatus;
    }
    
    private int getApiLimit(String apiType) {
        // 简化版本，实际应该从配置中读取
        // 注意：auth接口不在用户限流范围内，由IP限流保护
        switch (apiType) {
            case "water": return 300;
            case "user": return 120;
            case "device": return 150;
            case "stats": return 100;
            case "upload": return 30;
            default: return 150;
        }
    }
    
    /**
     * 用户限流调整请求
     */
    @Data
    public static class UserRateLimitAdjustRequest {
        private String apiType;
        private int maxRequests;
        private int windowSeconds;
        private String reason;
    }
    
    /**
     * 降级请求
     */
    @Data
    public static class DegradationRequest {
        private String apiType;
        private int durationMinutes;
        private String reason;
    }
}
